import drivers from './driver';
import DB from './db';

/**
 * 数据库操作工具对象
 */
export default class DBTool {
    /**
     * @param config 连接配置参数（参见DB）
     * @param driver 数据库驱动
     */
    constructor(config, driver) {
        if (!driver) {
            if (config instanceof DB) {
                driver = config;
            } else if (config) {
                driver = DBTool.make(config);
            } else {
                throw new Error('no config');
            }
        }
        this.db = driver;
    }

    /**
     * 创建数据库驱动
     * @param config 连接配置参数（参见DB）
     */
    static make(config) {
        const cfg = config || {};
        const type = cfg.type || 'mysql';
        const Driver = drivers.get(type);
        if (!Driver) {
            throw new Error(`DB type "${cfg.type}" NOT supported`);
        }
        return new Driver(config);
    }

    /// 测试用
    get _() {
        return this.db;
    }

    /**
     * 执行数据库操作（默认不启用事务并自动关闭连接）
     * @param action 数据库操作回调（参数为db）
     * @param options 不定选项（如果有两个，则第一个代表是否启用事务，第二个代表是否自动关闭连接。
     * 如果只有一个，则boolean类型代表是否启用事务，其它类型（如1或0）代表是否自动关闭连接。）
     * @return {*|Window}
     */
    run(action, ...options) {
        let withTransaction = false;
        let autoClose = true;
        if (options.length > 1) {
            withTransaction = options[0];
            autoClose = options[1];
        } else if (options.length) {
            switch (typeof options[0]) {
            case 'boolean':
                withTransaction = options[0];
                break;
            default:
                autoClose = options[0];
                break;
            }
        }

        const db = this.db;
        // 首先打开连接
        let res = db.open();
        // 是否启用事务
        if (withTransaction) {
            res = res.then(db => db.begin());
        }
        // 执行数据操作
        if (action) {
            res = res.then(action);
        }
        // 事务后续处理
        if (withTransaction) {
            res = res.then(res => db.commit().then(() => res))
                .catch(err => {
                    db.abort();
                    throw err;
                });
        }
        if (autoClose) {
            // 正常关闭
            res = res.then(res => {
                db.close();
                return res;
            });
            // 异常关闭
            res = res.catch(err => {
                db.close();
                throw err;
            });
        }
        return res;
    }

    /**
     * 关闭当前数据库连接
     * @return {*}
     */
    close() {
        if (this.db) {
            return this.db.close();
        }
    }
}
